package com.zly.framework.rbac.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.read.listener.PageReadListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zly.framework.rbac.model.entity.User;
import com.zly.framework.rbac.exception.SystemException;
import com.zly.framework.rbac.service.UserService;
import com.zly.framework.rbac.vaildate.EntityInsert;
import com.zly.framework.rbac.vaildate.EntityUpdate;
import com.zly.framework.rbac.model.vo.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

@Tag(name = "用户接口")
@RestController
@RequestMapping("/sys/user")
public class UserController {

    @Resource
    private UserService userServiceImpl;

    @Resource
    private PasswordEncoder passwordEncoder;

    @Operation(summary = "获取当前用户", description = "获取当前用户")
    @GetMapping
    public Result<User> info() {
        String username = SecurityContextHolder.getContext().getAuthentication().getName();
        if (Objects.equals(username, "anonymousUser")) {
            throw new SystemException("用户信息丢失");
        }
        User userInfoByUsername = userServiceImpl.getUserInfoByUsername(username);
        return Result.SUCCESS(userInfoByUsername);
    }

    @Operation(summary = "添加用户", description = "添加用户")
    @PostMapping
    public Result<Object> add(@Validated(value = {EntityInsert.class}) User user) {
        userServiceImpl.addNewUser(user);
        return Result.SUCCESS();
    }

    @Operation(summary = "修改用户信息", description = "修改用户信息")
    @PutMapping
    public Result<Object> updateInfo(@Validated(value = {EntityUpdate.class}) User user) {
        user.setPassword(null); // 防止密码被修改
        userServiceImpl.update(user, new LambdaQueryWrapper<User>().eq(User::getId, user.getId()));
        return Result.SUCCESS();
    }

    @Operation(summary = "删除用户信息", description = "删除用户信息")
    @DeleteMapping
    public Result<Object> delete(List<Long> ids) {
        userServiceImpl.removeBatchByIds(ids);
        return Result.SUCCESS();
    }

    @Operation(summary = "分页所有用户", description = "所有用户")
    @GetMapping("/page")
    public Result<IPage<User>> getAllUser(@RequestParam(name = "current", defaultValue = "1") Long current,
                                          @RequestParam(name = "size", defaultValue = "10") Long size) {
        Page<User> userPage = userServiceImpl.page(new Page<>(current, size));
        return Result.SUCCESS(userPage);
    }

    @Operation(summary = "修改密码", description = "修改密码")
    @PutMapping("/password")
    public Result<Object> updatePass(String oldPassword, String newPassword) {
        String username = SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString();
        User user = userServiceImpl.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if (passwordEncoder.matches(oldPassword, user.getPassword())) {
            user.setPassword(passwordEncoder.encode(newPassword));
            userServiceImpl.saveOrUpdate(user);
        } else {
            throw new SystemException("密码错误");
        }
        return Result.SUCCESS();
    }


    @Operation(summary = "检查用户名是否存在", description = "检查用户名是否存在")
    @GetMapping("/checkUsername")
    public Result<Object> checkUsername(String username) {
        User one = userServiceImpl.getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        if (one == null) {
            return Result.SUCCESS();
        } else {
            User user = new User();
            user.setUsername(one.getUsername());
            return Result.SUCCESS(user);
        }
    }

    @Operation(summary = "给用户分配角色", description = "给用户分配角色")
    @PostMapping("/grantRole")
    public Result<Object> grantRole(@RequestParam List<Long> userIds, @RequestParam List<Long> roleIds) {
        userServiceImpl.grantRoles(userIds, roleIds);
        return Result.SUCCESS();
    }

    @Operation(summary = "excel批量导入用户", description = "excel批量导入用户")
    @PostMapping("/file")
    public Result<Object> excelFile(MultipartFile file) throws IOException {
        InputStream inputStream = file.getInputStream();
        HashMap<String, List<User>> resultMap = new HashMap<>();
        ArrayList<User> userList = new ArrayList<>();
        EasyExcel.read(inputStream, User.class, new PageReadListener<User>(users -> users.forEach(user -> {
            String password = user.getPassword();
            String encodePassword = passwordEncoder.encode(password);
            user.setPassword(encodePassword);
            userList.add(user);
        }))).sheet().doRead();
        // todo: 统计成功和失败
        userServiceImpl.saveBatch(userList);
        ArrayList<User> errorList = new ArrayList<>();
        ArrayList<User> successList = new ArrayList<>(userList);
        resultMap.put("success", successList);
        resultMap.put("error", errorList);
        return Result.SUCCESS(resultMap);
    }

    @Operation(summary = "导出用户信息")
    @GetMapping(value = "/file")
    public void exportExcel(HttpServletResponse response, @RequestParam List<Long> ids) throws IOException {
        String filename = "用户信息.xlsx";
        response.setContentType("application/vnd.ms-excel;charset=utf-8");
        response.setHeader("Content-disposition", "attachment;filename=" + filename);
        response.flushBuffer();
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (!ids.isEmpty()) {
            queryWrapper.in(User::getId, ids);
        }
        List<User> list = userServiceImpl.list(queryWrapper);
        EasyExcel.write(response.getOutputStream(), User.class)
                .sheet("用户信息")
                .doWrite(list);
    }
}
